package com.hanserwei.community.uitils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class JWTUtils {

    // 密钥，使用 Keys.secretKeyFor(SignatureAlgorithm.HS256) 生成
    private static final String SECRET_STRING = "my-secret-key-here-at-least-32-characters-Hanswerner"; // 至少32个字符
    private static final SecretKey SECRET_KEY = Keys.hmacShaKeyFor(SECRET_STRING.getBytes());

    // JWT 过期时间（毫秒），例如 1 小时
    private static final long EXPIRATION_TIME = 60 * 60 * 1000L;

    /**
     * 生成 JWT Token
     *
     * @param claims 载荷，包含自定义信息
     * @return 生成的 JWT 字符串
     */
    public static String generateToken(Map<String, Object> claims) {
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        Date expiration = new Date(nowMillis + EXPIRATION_TIME);

        return Jwts.builder()
                .claims(claims) // 新版使用 claims() 设置载荷
                .issuedAt(now)
                .expiration(expiration) // 新版使用 expiration() 设置过期时间
                .signWith(SECRET_KEY) // 使用 SecretKey 签名
                .compact();
    }

    /**
     * 解析 JWT Token 并返回 Claims
     *
     * @param token JWT 字符串
     * @return Claims 对象
     */
    public static Claims parseToken(String token) {
        return Jwts.parser()
                .verifyWith(SECRET_KEY) // 新版使用 verifyWith() 验证签名
                .build()
                .parseSignedClaims(token) // 新版使用 parseSignedClaims()
                .getPayload(); // 获取载荷
    }

    /**
     * 验证 Token 是否有效
     *
     * @param token JWT 字符串
     * @return 如果有效且未过期，返回 true；否则返回 false
     */
    public static boolean validateToken(String token) {
        try {
            parseToken(token);
            log.info(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 从 Token 中获取自定义载荷
     *
     * @param token JWT 字符串
     * @return 载荷 Map
     */
    public static Map<String, Object> getClaimsFromToken(String token) {
        return parseToken(token);
    }

    /**
     * 使用现有 claims 刷新 token，生成新的过期时间
     */
    public static String refreshToken(Claims claims) {
        Map<String, Object> refreshedClaims = new HashMap<>(claims);
        refreshedClaims.remove(Claims.EXPIRATION);
        refreshedClaims.remove(Claims.ISSUED_AT);
        refreshedClaims.remove(Claims.NOT_BEFORE);
        return generateToken(refreshedClaims);
    }

    /**
     * 基于旧 token 刷新，重新生成过期时间
     */
    public static String refreshToken(String token) {
        return refreshToken(parseToken(token));
    }

    /**
     * 从 Token 中获取指定 key 的值
     *
     * @param token        JWT 字符串
     * @param key          载荷中的 key
     * @param requiredType 载荷中的 key 对应的值的类型
     * @param <T>          返回值的类型
     * @return 对应的值，如果不存在则返回 null
     */
    public static <T> T getClaimFromToken(String token, String key, Class<T> requiredType) {
        return parseToken(token).get(key, requiredType);
    }

}
